// ===============================
// top.v
// ===============================
module top(
    input  wire clk,             // System clock 50 MHz
    input  wire rst_n,           // Active-low reset
    input  wire LR,              // Left/Right channel select (未用)
    input  wire i2s_data,        // I2S serial data input
    
    input               clear_key,
	input               on_key,
    
    output wire [3:0]  Key_Row,     // 行输出（低有效）
    input  wire [3:0]  Key_Col,     // 列输入
    
    output				i2c_scl,	//i2c时钟线
	inout				i2c_sda,	//i2c数据线
    
    output wire i2s_bclk,        // I2S bit clock
    output wire i2s_lrclk,       // I2S left-right clock

    output wire out_i2s_data,    // Filtered I2S data output
    output wire out_i2s_data_vld,
    output wire out_i2s_bclk,
    output wire out_i2s_lrclk,

    output wire [7:0] digit_seg,
    output wire [3:0] digit_dig
);

// ===============================
// I²S 接收
// ===============================
wire [23:0] rxdata_l;
wire        rxdata_vld_l;


i2s_recieve_top u_i2s_reciever_top (
    .i_clk_50m           (clk),
    .i_rst_n             (rst_n),
    .i_i2s_sdata         (i2s_data),
    .o_i2s_mclk          (),                 // 未用
    .o_i2s_bclk          (i2s_bclk),
    .o_i2s_lrclk         (i2s_lrclk),
    .o_i2s_rxdata_l      (rxdata_l),
    .o_i2s_rxdata_r      (),
    .o_i2s_rxdata_vld_l  (rxdata_vld_l),
    .o_i2s_rxdata_vld_r  ()
);

// ===============================
// 24 bit → 16 bit 通道选择
// ===============================
wire [23:0] selected_channel     = rxdata_l;      // 仅用左声道
wire        selected_channel_vld = rxdata_vld_l;

wire signed [15:0] b16_data;
wire               b16_data_vld;

from_24bit_to_16bit u_24_to_16 (
    .rst_n        (rst_n),
    .clk          (i2s_bclk),
    .data_vld_in  (selected_channel_vld),
    .data_in      (selected_channel),
    .data_vld_out (b16_data_vld),
    .data_out     (b16_data)
);

// ===============================
// FIR 带通滤波（I2S_BCLK 域）
// ===============================
wire signed [35:0] y36;       // 36-bit 累加结果
wire               y36_vld;   // 与 y36 对齐

fir_bandpass #(
    .N(63)
) u_fir_bandpass (
    .clk        (i2s_bclk),
    .rst_n      (rst_n),
    .en         (b16_data_vld),
    .xin        (b16_data),
    .yout       (y36),
    .yout_valid (y36_vld)
);

// ======== +20 dB post-gain：缩放 + 饱和到 16bit（Q15） ========
localparam integer OUT_SHIFT  = 16;    // 你的原基准缩放
localparam integer GAIN_NUM   = 10240; // = 10 * 1024  → 精确 ×10（+20 dB）
localparam integer GAIN_SHIFT = 10;    // 除以 1024

// 36b × 14b → 50b，留富余用 52b
wire signed [51:0] y36_mul    = $signed(y36) * $signed(GAIN_NUM);
wire signed [51:0] y_scaled   = y36_mul >>> (OUT_SHIFT + GAIN_SHIFT);

// 16 位饱和
wire signed [15:0] out_data =
    (y_scaled >  52'sd32767)  ? 16'sd32767  :
    (y_scaled < -52'sd32768)  ? -16'sd32768 :
                                 y_scaled[15:0];

wire out_data_vld_int = y36_vld;




// ===============================
// 数码管监控与显示（使用滤波后的幅度）
// ===============================
digit_monitor #(
    .T0_COUNT(20'd1_000_000) // ≈20ms@50MHz，保持你的常数
) u_digit_monitor (
    .clk        (clk),
    .rst_n      (rst_n),
    .i2s_bclk   (i2s_bclk),
    .b16_data   (out_data),
    .b16_vld    (out_data_vld_int),
    .digit_seg  (digit_seg),
    .digit_dig  (digit_dig)
);



// ===============================
// 矩阵键盘信息获取
// ===============================
wire [15:0] btn_matrix_state;

matrix_keypad u_matrix_keypad(
    .clk(clk),
    .rst_n(rst_n),
    .Key_Row(Key_Row),
    .Key_Col(Key_Col),
    .key_state(btn_matrix_state)
);

// ===============================
// OLED监控与显示
// ===============================
reg[30:0]   clk_en;
reg clk_ccc;


always@(posedge clk or negedge rst_n)
begin
    if(rst_n == 1'b0)
        clk_en <= 'd0;
    else if(clk_en >= 'd10)
        clk_en <= 'd0;
    else
        clk_en <= clk_en + 1'b1;
end

always@(posedge clk or negedge rst_n)
begin
    if(rst_n == 1'b0)
        clk_ccc <= 'd0;
    else if(clk_en >= 'd10)
        clk_ccc <= ~clk_ccc;
    else
        clk_ccc <= clk_ccc;

end


		
		
Oled_Top	Oled_Top_HP(

	
	.clk			(clk),
	.rst			(rst_n),
	
	.clear_key    (clear_key),
	.on_key        (on_key),
    
    .matrix_state  (btn_matrix_state),
	
	.scl			(i2c_scl),
	.sda			(i2c_sda)
);

// ===============================
// I²S 发送（保留原功能）
// ===============================
i2s_transmit_top u_i2s_transmit_top (
    .i_clk_50m        (clk),
    .i_rst_n          (rst_n),
    .i_i2s_txdata_l   (out_data),
    .i_i2s_txdata_r   (out_data),
    .i_i2s_txdata_vld (out_data_vld_int),
    .o_i2s_sdata      (out_i2s_data),
    .o_i2s_mclk       (),
    .o_i2s_bclk       (out_i2s_bclk),
    .o_i2s_lrclk      (out_i2s_lrclk),
    .o_i2s_tx_ready   ()
);

assign out_i2s_data_vld = out_data_vld_int;

endmodule













// matrix顶层例化
module top_matrix(
    input  wire clk,             // System clock 50 MHz
    input  wire rst_n,           // Active-low reset
    input  wire LR,              // 未用

    input  wire [3:0] i2s_data_L1,
    input  wire [3:0] i2s_data_L2,
    input  wire [3:0] i2s_data_L3,
    input  wire [3:0] i2s_data_L4,

    input               clear_key,
    input               on_key,

    output wire [3:0]  Key_Row,
    input  wire [3:0]  Key_Col,

    output              i2c_scl,
    inout               i2c_sda,

    // 接收侧 I²S 时钟（来自 u_i2s_reciever_0）
    output wire i2s_bclk,
    output wire i2s_lrclk,

    // 发送侧 I²S 输出（来自 TX）
    output wire out_i2s_data,
    output wire out_i2s_data_vld,
    output wire out_i2s_bclk,
    output wire out_i2s_lrclk,

    output wire [7:0] digit_seg,
    output wire [3:0] digit_dig
);

    // ===== 增益/缩放，保持与“上面 top”一致 =====
    localparam integer OUT_SHIFT  = 16;
    localparam integer GAIN_NUM   = 10240; // ≈ ×10 (+20dB)
    localparam integer GAIN_SHIFT = 10;

    // ===============================
    // I²S 接收（以第0路为“主时钟源”）
    // ===============================
    wire [23:0] rxdata_l_0;  wire rxvld_l_0;
    wire        i2s_bclk_shared, i2s_lrclk_shared;

    i2s_recieve_top u_i2s_reciever_0 (
        .i_clk_50m          (clk),
        .i_rst_n            (rst_n),
        .i_i2s_sdata        (i2s_data_L1[0]),
        .o_i2s_mclk         (),
        .o_i2s_bclk         (i2s_bclk_shared),
        .o_i2s_lrclk        (i2s_lrclk_shared),
        .o_i2s_rxdata_l     (rxdata_l_0),
        .o_i2s_rxdata_r     (),
        .o_i2s_rxdata_vld_l (rxvld_l_0),
        .o_i2s_rxdata_vld_r ()
    );

    assign i2s_bclk  = i2s_bclk_shared;
    assign i2s_lrclk = i2s_lrclk_shared;

    // 其余 15 路接收器（忽略其 o_i2s_bclk/lrclk，仅取数据/有效）
    // -- Line1 ch1..3
    wire [23:0] rxdata_l_1;  wire rxvld_l_1;
    wire [23:0] rxdata_l_2;  wire rxvld_l_2;
    wire [23:0] rxdata_l_3;  wire rxvld_l_3;
    i2s_recieve_top u_i2s_reciever_1 (.i_clk_50m(clk), .i_rst_n(rst_n), .i_i2s_sdata(i2s_data_L1[1]), .o_i2s_mclk(), .o_i2s_bclk(), .o_i2s_lrclk(), .o_i2s_rxdata_l(rxdata_l_1), .o_i2s_rxdata_r(), .o_i2s_rxdata_vld_l(rxvld_l_1), .o_i2s_rxdata_vld_r());
    i2s_recieve_top u_i2s_reciever_2 (.i_clk_50m(clk), .i_rst_n(rst_n), .i_i2s_sdata(i2s_data_L1[2]), .o_i2s_mclk(), .o_i2s_bclk(), .o_i2s_lrclk(), .o_i2s_rxdata_l(rxdata_l_2), .o_i2s_rxdata_r(), .o_i2s_rxdata_vld_l(rxvld_l_2), .o_i2s_rxdata_vld_r());
    i2s_recieve_top u_i2s_reciever_3 (.i_clk_50m(clk), .i_rst_n(rst_n), .i_i2s_sdata(i2s_data_L1[3]), .o_i2s_mclk(), .o_i2s_bclk(), .o_i2s_lrclk(), .o_i2s_rxdata_l(rxdata_l_3), .o_i2s_rxdata_r(), .o_i2s_rxdata_vld_l(rxvld_l_3), .o_i2s_rxdata_vld_r());
    // -- Line2 ch4..7
    wire [23:0] rxdata_l_4;  wire rxvld_l_4;
    wire [23:0] rxdata_l_5;  wire rxvld_l_5;
    wire [23:0] rxdata_l_6;  wire rxvld_l_6;
    wire [23:0] rxdata_l_7;  wire rxvld_l_7;
    i2s_recieve_top u_i2s_reciever_4 (.i_clk_50m(clk), .i_rst_n(rst_n), .i_i2s_sdata(i2s_data_L2[0]), .o_i2s_mclk(), .o_i2s_bclk(), .o_i2s_lrclk(), .o_i2s_rxdata_l(rxdata_l_4), .o_i2s_rxdata_r(), .o_i2s_rxdata_vld_l(rxvld_l_4), .o_i2s_rxdata_vld_r());
    i2s_recieve_top u_i2s_reciever_5 (.i_clk_50m(clk), .i_rst_n(rst_n), .i_i2s_sdata(i2s_data_L2[1]), .o_i2s_mclk(), .o_i2s_bclk(), .o_i2s_lrclk(), .o_i2s_rxdata_l(rxdata_l_5), .o_i2s_rxdata_r(), .o_i2s_rxdata_vld_l(rxvld_l_5), .o_i2s_rxdata_vld_r());
    i2s_recieve_top u_i2s_reciever_6 (.i_clk_50m(clk), .i_rst_n(rst_n), .i_i2s_sdata(i2s_data_L2[2]), .o_i2s_mclk(), .o_i2s_bclk(), .o_i2s_lrclk(), .o_i2s_rxdata_l(rxdata_l_6), .o_i2s_rxdata_r(), .o_i2s_rxdata_vld_l(rxvld_l_6), .o_i2s_rxdata_vld_r());
    i2s_recieve_top u_i2s_reciever_7 (.i_clk_50m(clk), .i_rst_n(rst_n), .i_i2s_sdata(i2s_data_L2[3]), .o_i2s_mclk(), .o_i2s_bclk(), .o_i2s_lrclk(), .o_i2s_rxdata_l(rxdata_l_7), .o_i2s_rxdata_r(), .o_i2s_rxdata_vld_l(rxvld_l_7), .o_i2s_rxdata_vld_r());
    // -- Line3 ch8..11
    wire [23:0] rxdata_l_8;  wire rxvld_l_8;
    wire [23:0] rxdata_l_9;  wire rxvld_l_9;
    wire [23:0] rxdata_l_10; wire rxvld_l_10;
    wire [23:0] rxdata_l_11; wire rxvld_l_11;
    i2s_recieve_top u_i2s_reciever_8  (.i_clk_50m(clk), .i_rst_n(rst_n), .i_i2s_sdata(i2s_data_L3[0]), .o_i2s_mclk(), .o_i2s_bclk(), .o_i2s_lrclk(), .o_i2s_rxdata_l(rxdata_l_8 ), .o_i2s_rxdata_r(), .o_i2s_rxdata_vld_l(rxvld_l_8 ), .o_i2s_rxdata_vld_r());
    i2s_recieve_top u_i2s_reciever_9  (.i_clk_50m(clk), .i_rst_n(rst_n), .i_i2s_sdata(i2s_data_L3[1]), .o_i2s_mclk(), .o_i2s_bclk(), .o_i2s_lrclk(), .o_i2s_rxdata_l(rxdata_l_9 ), .o_i2s_rxdata_r(), .o_i2s_rxdata_vld_l(rxvld_l_9 ), .o_i2s_rxdata_vld_r());
    i2s_recieve_top u_i2s_reciever_10 (.i_clk_50m(clk), .i_rst_n(rst_n), .i_i2s_sdata(i2s_data_L3[2]), .o_i2s_mclk(), .o_i2s_bclk(), .o_i2s_lrclk(), .o_i2s_rxdata_l(rxdata_l_10), .o_i2s_rxdata_r(), .o_i2s_rxdata_vld_l(rxvld_l_10), .o_i2s_rxdata_vld_r());
    i2s_recieve_top u_i2s_reciever_11 (.i_clk_50m(clk), .i_rst_n(rst_n), .i_i2s_sdata(i2s_data_L3[3]), .o_i2s_mclk(), .o_i2s_bclk(), .o_i2s_lrclk(), .o_i2s_rxdata_l(rxdata_l_11), .o_i2s_rxdata_r(), .o_i2s_rxdata_vld_l(rxvld_l_11), .o_i2s_rxdata_vld_r());
    // -- Line4 ch12..15
    wire [23:0] rxdata_l_12; wire rxvld_l_12;
    wire [23:0] rxdata_l_13; wire rxvld_l_13;
    wire [23:0] rxdata_l_14; wire rxvld_l_14;
    wire [23:0] rxdata_l_15; wire rxvld_l_15;
    i2s_recieve_top u_i2s_reciever_12 (.i_clk_50m(clk), .i_rst_n(rst_n), .i_i2s_sdata(i2s_data_L4[0]), .o_i2s_mclk(), .o_i2s_bclk(), .o_i2s_lrclk(), .o_i2s_rxdata_l(rxdata_l_12), .o_i2s_rxdata_r(), .o_i2s_rxdata_vld_l(rxvld_l_12), .o_i2s_rxdata_vld_r());
    i2s_recieve_top u_i2s_reciever_13 (.i_clk_50m(clk), .i_rst_n(rst_n), .i_i2s_sdata(i2s_data_L4[1]), .o_i2s_mclk(), .o_i2s_bclk(), .o_i2s_lrclk(), .o_i2s_rxdata_l(rxdata_l_13), .o_i2s_rxdata_r(), .o_i2s_rxdata_vld_l(rxvld_l_13), .o_i2s_rxdata_vld_r());
    i2s_recieve_top u_i2s_reciever_14 (.i_clk_50m(clk), .i_rst_n(rst_n), .i_i2s_sdata(i2s_data_L4[2]), .o_i2s_mclk(), .o_i2s_bclk(), .o_i2s_lrclk(), .o_i2s_rxdata_l(rxdata_l_14), .o_i2s_rxdata_r(), .o_i2s_rxdata_vld_l(rxvld_l_14), .o_i2s_rxdata_vld_r());
    i2s_recieve_top u_i2s_reciever_15 (.i_clk_50m(clk), .i_rst_n(rst_n), .i_i2s_sdata(i2s_data_L4[3]), .o_i2s_mclk(), .o_i2s_bclk(), .o_i2s_lrclk(), .o_i2s_rxdata_l(rxdata_l_15), .o_i2s_rxdata_r(), .o_i2s_rxdata_vld_l(rxvld_l_15), .o_i2s_rxdata_vld_r());

    // ===============================
    // 24 -> 16（全部在 i2s_bclk_shared 域）
    // ===============================
    wire signed [15:0] d16 [0:15];
    wire               v16 [0:15];

    from_24bit_to_16bit u_24to16_0  (.rst_n(rst_n), .clk(i2s_bclk_shared), .data_vld_in(rxvld_l_0 ), .data_in(rxdata_l_0 ), .data_vld_out(v16[0 ]), .data_out(d16[0 ]));
    from_24bit_to_16bit u_24to16_1  (.rst_n(rst_n), .clk(i2s_bclk_shared), .data_vld_in(rxvld_l_1 ), .data_in(rxdata_l_1 ), .data_vld_out(v16[1 ]), .data_out(d16[1 ]));
    from_24bit_to_16bit u_24to16_2  (.rst_n(rst_n), .clk(i2s_bclk_shared), .data_vld_in(rxvld_l_2 ), .data_in(rxdata_l_2 ), .data_vld_out(v16[2 ]), .data_out(d16[2 ]));
    from_24bit_to_16bit u_24to16_3  (.rst_n(rst_n), .clk(i2s_bclk_shared), .data_vld_in(rxvld_l_3 ), .data_in(rxdata_l_3 ), .data_vld_out(v16[3 ]), .data_out(d16[3 ]));
    from_24bit_to_16bit u_24to16_4  (.rst_n(rst_n), .clk(i2s_bclk_shared), .data_vld_in(rxvld_l_4 ), .data_in(rxdata_l_4 ), .data_vld_out(v16[4 ]), .data_out(d16[4 ]));
    from_24bit_to_16bit u_24to16_5  (.rst_n(rst_n), .clk(i2s_bclk_shared), .data_vld_in(rxvld_l_5 ), .data_in(rxdata_l_5 ), .data_vld_out(v16[5 ]), .data_out(d16[5 ]));
    from_24bit_to_16bit u_24to16_6  (.rst_n(rst_n), .clk(i2s_bclk_shared), .data_vld_in(rxvld_l_6 ), .data_in(rxdata_l_6 ), .data_vld_out(v16[6 ]), .data_out(d16[6 ]));
    from_24bit_to_16bit u_24to16_7  (.rst_n(rst_n), .clk(i2s_bclk_shared), .data_vld_in(rxvld_l_7 ), .data_in(rxdata_l_7 ), .data_vld_out(v16[7 ]), .data_out(d16[7 ]));
    from_24bit_to_16bit u_24to16_8  (.rst_n(rst_n), .clk(i2s_bclk_shared), .data_vld_in(rxvld_l_8 ), .data_in(rxdata_l_8 ), .data_vld_out(v16[8 ]), .data_out(d16[8 ]));
    from_24bit_to_16bit u_24to16_9  (.rst_n(rst_n), .clk(i2s_bclk_shared), .data_vld_in(rxvld_l_9 ), .data_in(rxdata_l_9 ), .data_vld_out(v16[9 ]), .data_out(d16[9 ]));
    from_24bit_to_16bit u_24to16_10 (.rst_n(rst_n), .clk(i2s_bclk_shared), .data_vld_in(rxvld_l_10), .data_in(rxdata_l_10), .data_vld_out(v16[10]), .data_out(d16[10]));
    from_24bit_to_16bit u_24to16_11 (.rst_n(rst_n), .clk(i2s_bclk_shared), .data_vld_in(rxvld_l_11), .data_in(rxdata_l_11), .data_vld_out(v16[11]), .data_out(d16[11]));
    from_24bit_to_16bit u_24to16_12 (.rst_n(rst_n), .clk(i2s_bclk_shared), .data_vld_in(rxvld_l_12), .data_in(rxdata_l_12), .data_vld_out(v16[12]), .data_out(d16[12]));
    from_24bit_to_16bit u_24to16_13 (.rst_n(rst_n), .clk(i2s_bclk_shared), .data_vld_in(rxvld_l_13), .data_in(rxdata_l_13), .data_vld_out(v16[13]), .data_out(d16[13]));
    from_24bit_to_16bit u_24to16_14 (.rst_n(rst_n), .clk(i2s_bclk_shared), .data_vld_in(rxvld_l_14), .data_in(rxdata_l_14), .data_vld_out(v16[14]), .data_out(d16[14]));
    from_24bit_to_16bit u_24to16_15 (.rst_n(rst_n), .clk(i2s_bclk_shared), .data_vld_in(rxvld_l_15), .data_in(rxdata_l_15), .data_vld_out(v16[15]), .data_out(d16[15]));

    // ===============================
    // 矩阵键盘 & OLED（仍在 50MHz 域；按要求不做CDC）
    // ===============================
    wire [15:0] btn_matrix_state;
    matrix_keypad u_matrix_keypad(
        .clk(clk), .rst_n(rst_n),
        .Key_Row(Key_Row), .Key_Col(Key_Col),
        .key_state(btn_matrix_state)
    );

    wire [11:0] pitch;
    wire [11:0] yaw;

    // 小节拍器（与上面 top 相同风格，功能无强依赖）
    reg [30:0] clk_en; reg clk_ccc;
    always @(posedge clk or negedge rst_n) begin
        if(!rst_n) clk_en <= 0;
        else if(clk_en >= 31'd10) clk_en <= 0;
        else clk_en <= clk_en + 1'b1;
    end
    always @(posedge clk or negedge rst_n) begin
        if(!rst_n) clk_ccc <= 1'b0;
        else if(clk_en >= 31'd10) clk_ccc <= ~clk_ccc;
        else clk_ccc <= clk_ccc;
    end

    Oled_Top Oled_Top_HP(
        .clk          (clk),
        .rst          (rst_n),
        .clear_key    (clear_key),
        .on_key       (on_key),
        .matrix_state (btn_matrix_state),
        .scl          (i2c_scl),
        .sda          (i2c_sda),
        .pitch        (pitch),
        .yaw          (yaw)
    );

    // ===============================
    // 方位 → 16路时延（直接在 bclk 域运算，无CDC）
    // ===============================
    reg [11:0] pitch_bclk, yaw_bclk, pitch_bclk_d, yaw_bclk_d;
    always @(posedge i2s_bclk_shared or negedge rst_n) begin
        if(!rst_n) begin
            pitch_bclk<=12'd0; yaw_bclk<=12'd0;
            pitch_bclk_d<=12'd0; yaw_bclk_d<=12'd0;
        end else begin
            pitch_bclk   <= pitch;
            yaw_bclk     <= yaw;
            pitch_bclk_d <= pitch_bclk;
            yaw_bclk_d   <= yaw_bclk;
        end
    end
    wire start_calc = (pitch_bclk != pitch_bclk_d) || (yaw_bclk != yaw_bclk_d);

    wire [15:0] time_delays_0,  time_delays_1,  time_delays_2,  time_delays_3;
    wire [15:0] time_delays_4,  time_delays_5,  time_delays_6,  time_delays_7;
    wire [15:0] time_delays_8,  time_delays_9,  time_delays_10, time_delays_11;
    wire [15:0] time_delays_12, time_delays_13, time_delays_14, time_delays_15;
    wire delay_calc_valid, calc_done;

    time_delay_calc u_time_delay_calc(
        .clk           (i2s_bclk_shared),
        .rst_n         (rst_n),
        .start_calc    (start_calc),
        .phi           (yaw_bclk),
        .theta         (pitch_bclk),
        .time_delays_0 (time_delays_0 ),
        .time_delays_1 (time_delays_1 ),
        .time_delays_2 (time_delays_2 ),
        .time_delays_3 (time_delays_3 ),
        .time_delays_4 (time_delays_4 ),
        .time_delays_5 (time_delays_5 ),
        .time_delays_6 (time_delays_6 ),
        .time_delays_7 (time_delays_7 ),
        .time_delays_8 (time_delays_8 ),
        .time_delays_9 (time_delays_9 ),
        .time_delays_10(time_delays_10),
        .time_delays_11(time_delays_11),
        .time_delays_12(time_delays_12),
        .time_delays_13(time_delays_13),
        .time_delays_14(time_delays_14),
        .time_delays_15(time_delays_15),
        .calc_done     (calc_done),
        .valid         (delay_calc_valid)
    );

    // ===============================
    // 16路合成（无CDC）→ FIR → 增益/饱和
    // ===============================
    wire signed [15:0] sum_data;
    wire               sum_data_vld;
    
    wire signed [15:0] W1 = 16'sh7FFF;

    sig_add  u_sig_add (
        .clk   (i2s_bclk_shared),
        .rst_n (rst_n),

        .in_data_0 (d16[0 ]), .in_data_1 (d16[1 ]), .in_data_2 (d16[2 ]), .in_data_3 (d16[3 ]),
        .in_data_4 (d16[4 ]), .in_data_5 (d16[5 ]), .in_data_6 (d16[6 ]), .in_data_7 (d16[7 ]),
        .in_data_8 (d16[8 ]), .in_data_9 (d16[9 ]), .in_data_10(d16[10]), .in_data_11(d16[11]),
        .in_data_12(d16[12]), .in_data_13(d16[13]), .in_data_14(d16[14]), .in_data_15(d16[15]),

        .in_data_vld_0 (v16[0 ]), .in_data_vld_1 (v16[1 ]), .in_data_vld_2 (v16[2 ]), .in_data_vld_3 (v16[3 ]),
        .in_data_vld_4 (v16[4 ]), .in_data_vld_5 (v16[5 ]), .in_data_vld_6 (v16[6 ]), .in_data_vld_7 (v16[7 ]),
        .in_data_vld_8 (v16[8 ]), .in_data_vld_9 (v16[9 ]), .in_data_vld_10(v16[10]), .in_data_vld_11(v16[11]),
        .in_data_vld_12(v16[12]), .in_data_vld_13(v16[13]), .in_data_vld_14(v16[14]), .in_data_vld_15(v16[15]),

        .in_data_delay_0 (time_delays_0 ), .in_data_delay_1 (time_delays_1 ), .in_data_delay_2 (time_delays_2 ),
        .in_data_delay_3 (time_delays_3 ), .in_data_delay_4 (time_delays_4 ), .in_data_delay_5 (time_delays_5 ),
        .in_data_delay_6 (time_delays_6 ), .in_data_delay_7 (time_delays_7 ), .in_data_delay_8 (time_delays_8 ),
        .in_data_delay_9 (time_delays_9 ), .in_data_delay_10(time_delays_10), .in_data_delay_11(time_delays_11),
        .in_data_delay_12(time_delays_12), .in_data_delay_13(time_delays_13), .in_data_delay_14(time_delays_14),
        .in_data_delay_15(time_delays_15),


        .out_proc_data     (sum_data),
        .out_proc_data_vld (sum_data_vld)
    );

    // FIR（与上面 top 的风格一致）
    wire signed [35:0] y36_filtered;
    wire               y36_vld_filtered;
    // 2×biquad IIR（示例：请填入你的 Q2.30 系数）
	// 建议：4 阶 Butterworth 低通 fc≈3.6~4.0kHz（抑制>fg 的栅瓣）
	wire signed [15:0] iir_out_16;
	wire               iir_vld;

	iir2x_df2t #(
    	 // Stage 1
    	.S1_B0(32'sd2267229),   .S1_B1(32'sd4534459),   .S1_B2(32'sd2267229),
    	.S1_A1(-32'sd1309825540), .S1_A2(32'sd416699726),
    	// Stage 2
    	.S2_B0(32'sd1052266988), .S2_B1(32'sd2104533975), .S2_B2(32'sd1052266988),
    	.S2_A1(-32'sd1595843209), .S2_A2(32'sd742157281)

	) u_iir_final (
    	.clk(i2s_bclk_shared),
    	.rst_n(rst_n),
    	.en(sum_data_vld),
    	.xin(sum_data),          // 这里 sum_data 是 16bit（你的 sig_add 输出）
    	.yout(iir_out_16),
    	.yout_valid(iir_vld)
	);

	// 直接作为最终结果送 FIFO/TX
	wire signed [15:0] out_proc_data   = iir_out_16;
	wire               out_proc_data_vld = iir_vld;



    // ===============================
    // 数码管监控（最终处理后的数据）
    // ===============================
    digit_monitor #(.T0_COUNT(20'd1_000_000)) u_digit_monitor (
        .clk       (clk),
        .rst_n     (rst_n),
        .i2s_bclk  (i2s_bclk_shared),
        .b16_data  (out_proc_data),
        .b16_vld   (out_proc_data_vld),
        .digit_seg (digit_seg),
        .digit_dig (digit_dig)
    );

    // ===============================
    // I²S 发送（保持和“上面 top”同样的接口语义）
    // ===============================
    i2s_transmit_top u_i2s_transmit_top (
        .i_clk_50m        (clk),
        .i_rst_n          (rst_n),
        .i_i2s_txdata_l   (out_proc_data),
        .i_i2s_txdata_r   (out_proc_data),
        .i_i2s_txdata_vld (out_proc_data_vld),
        .o_i2s_sdata      (out_i2s_data),
        .o_i2s_mclk       (),
        .o_i2s_bclk       (out_i2s_bclk),
        .o_i2s_lrclk      (out_i2s_lrclk),
        .o_i2s_tx_ready   ()
    );

    assign out_i2s_data_vld = out_proc_data_vld;

endmodule



`timescale 1ns/1ps
// ==========================================================
// sig_add.v  — Verilog-2001
// 16 路整数延迟 + 阵列加权（Kaiser 2D）+ 树形求和 + 归一化
// ==========================================================
module sig_add (
    input  wire        clk,              // i2s_bclk
    input  wire        rst_n,

    // 16路 16-bit 输入与有效
    input  wire signed [15:0] in_data_0,  input wire in_data_vld_0,
    input  wire signed [15:0] in_data_1,  input wire in_data_vld_1,
    input  wire signed [15:0] in_data_2,  input wire in_data_vld_2,
    input  wire signed [15:0] in_data_3,  input wire in_data_vld_3,
    input  wire signed [15:0] in_data_4,  input wire in_data_vld_4,
    input  wire signed [15:0] in_data_5,  input wire in_data_vld_5,
    input  wire signed [15:0] in_data_6,  input wire in_data_vld_6,
    input  wire signed [15:0] in_data_7,  input wire in_data_vld_7,
    input  wire signed [15:0] in_data_8,  input wire in_data_vld_8,
    input  wire signed [15:0] in_data_9,  input wire in_data_vld_9,
    input  wire signed [15:0] in_data_10, input wire in_data_vld_10,
    input  wire signed [15:0] in_data_11, input wire in_data_vld_11,
    input  wire signed [15:0] in_data_12, input wire in_data_vld_12,
    input  wire signed [15:0] in_data_13, input wire in_data_vld_13,
    input  wire signed [15:0] in_data_14, input wire in_data_vld_14,
    input  wire signed [15:0] in_data_15, input wire in_data_vld_15,

    // 16 路整数延迟（单位：采样点，需 < MAX_DELAY）
    input  wire [15:0] in_data_delay_0,
    input  wire [15:0] in_data_delay_1,
    input  wire [15:0] in_data_delay_2,
    input  wire [15:0] in_data_delay_3,
    input  wire [15:0] in_data_delay_4,
    input  wire [15:0] in_data_delay_5,
    input  wire [15:0] in_data_delay_6,
    input  wire [15:0] in_data_delay_7,
    input  wire [15:0] in_data_delay_8,
    input  wire [15:0] in_data_delay_9,
    input  wire [15:0] in_data_delay_10,
    input  wire [15:0] in_data_delay_11,
    input  wire [15:0] in_data_delay_12,
    input  wire [15:0] in_data_delay_13,
    input  wire [15:0] in_data_delay_14,
    input  wire [15:0] in_data_delay_15,

    output reg  signed [15:0] out_proc_data,
    output reg                out_proc_data_vld
);
    // -------- 参数：延迟线深度（必须 > 最大整数延迟）---------
    localparam integer MAX_DELAY = 26;  // 环形缓冲深度
    localparam integer AW        = 5;   // ceil(log2(27)) = 5

    // ===================== 强抑制版 Hamming 2D 权重（Q1.15） =====================
// 1D: [0.08, 0.77, 0.77, 0.08] → 2D乘积：
// 角落: 0.0064 → 210，边-近中心: 0.0616 → 2019，中心块: 0.5929 → 19428
localparam signed [15:0] W2D_0 = 16'sd210;   localparam signed [15:0] W2D_1 = 16'sd2019;
localparam signed [15:0] W2D_2 = 16'sd2019;  localparam signed [15:0] W2D_3 = 16'sd210;

localparam signed [15:0] W2D_4 = 16'sd2019;  localparam signed [15:0] W2D_5 = 16'sd19428;
localparam signed [15:0] W2D_6 = 16'sd19428; localparam signed [15:0] W2D_7 = 16'sd2019;

localparam signed [15:0] W2D_8 = 16'sd2019;  localparam signed [15:0] W2D_9 = 16'sd19428;
localparam signed [15:0] W2D_10 = 16'sd19428; localparam signed [15:0] W2D_11 = 16'sd2019;

localparam signed [15:0] W2D_12 = 16'sd210;   localparam signed [15:0] W2D_13 = 16'sd2019;
localparam signed [15:0] W2D_14 = 16'sd2019;  localparam signed [15:0] W2D_15 = 16'sd210;

// 归一化（保证主瓣同相平面波时总体幅度≈1）
// NORM_Q15 = round( (1<<15)*16 / sum(W2D)/2^15 )
localparam signed [31:0] NORM_Q15 = 32'sd181406; // 替换你原来的 NORM_Q15

    // 工具函数：环绕减法（针对 MAX_DELAY）
    function [AW-1:0] sub_mod;
        input [AW-1:0] a; 
        input [AW-1:0] b;
        reg   [AW:0]   tmp;
    begin
        if (a >= b) tmp = a - b;
        else        tmp = a + MAX_DELAY - b; // 整数相加减，再截位
        sub_mod = tmp[AW-1:0];
    end
    endfunction

    // ========== 通道 0 ==========
    reg signed [15:0] mem0 [0:MAX_DELAY-1];
    reg [AW-1:0] wr0; integer i0;
    always @(posedge clk or negedge rst_n) begin
        if(!rst_n) begin
            wr0 <= {AW{1'b0}};
            for(i0=0;i0<MAX_DELAY;i0=i0+1) mem0[i0] <= 16'sd0;
        end else if (in_data_vld_0) begin
            mem0[wr0] <= in_data_0;
            wr0 <= (wr0==MAX_DELAY-1) ? {AW{1'b0}} : wr0 + 1'b1;
        end
    end
    wire [AW-1:0] dly0 = (in_data_delay_0 >= MAX_DELAY) ? (MAX_DELAY-1) : in_data_delay_0[AW-1:0];
    wire [AW-1:0] rd0  = sub_mod(wr0, dly0);
    wire signed [15:0] d0 = mem0[rd0];
    wire signed [31:0] m0 = $signed(d0) * $signed(W2D_0);
    wire signed [15:0] w0 = m0[30:15];

    // ========== 通道 1 ==========
    reg signed [15:0] mem1 [0:MAX_DELAY-1];
    reg [AW-1:0] wr1; integer i1;
    always @(posedge clk or negedge rst_n) begin
        if(!rst_n) begin
            wr1 <= {AW{1'b0}};
            for(i1=0;i1<MAX_DELAY;i1=i1+1) mem1[i1] <= 16'sd0;
        end else if (in_data_vld_1) begin
            mem1[wr1] <= in_data_1;
            wr1 <= (wr1==MAX_DELAY-1) ? {AW{1'b0}} : wr1 + 1'b1;
        end
    end
    wire [AW-1:0] dly1 = (in_data_delay_1 >= MAX_DELAY) ? (MAX_DELAY-1) : in_data_delay_1[AW-1:0];
    wire [AW-1:0] rd1  = sub_mod(wr1, dly1);
    wire signed [15:0] d1 = mem1[rd1];
    wire signed [31:0] m1 = $signed(d1) * $signed(W2D_1);
    wire signed [15:0] w1 = m1[30:15];

    // ========== 通道 2 ==========
    reg signed [15:0] mem2 [0:MAX_DELAY-1];
    reg [AW-1:0] wr2; integer i2;
    always @(posedge clk or negedge rst_n) begin
        if(!rst_n) begin
            wr2 <= {AW{1'b0}};
            for(i2=0;i2<MAX_DELAY;i2=i2+1) mem2[i2] <= 16'sd0;
        end else if (in_data_vld_2) begin
            mem2[wr2] <= in_data_2;
            wr2 <= (wr2==MAX_DELAY-1) ? {AW{1'b0}} : wr2 + 1'b1;
        end
    end
    wire [AW-1:0] dly2 = (in_data_delay_2 >= MAX_DELAY) ? (MAX_DELAY-1) : in_data_delay_2[AW-1:0];
    wire [AW-1:0] rd2  = sub_mod(wr2, dly2);
    wire signed [15:0] d2 = mem2[rd2];
    wire signed [31:0] m2 = $signed(d2) * $signed(W2D_2);
    wire signed [15:0] w2 = m2[30:15];

    // ========== 通道 3 ==========
    reg signed [15:0] mem3 [0:MAX_DELAY-1];
    reg [AW-1:0] wr3; integer i3;
    always @(posedge clk or negedge rst_n) begin
        if(!rst_n) begin
            wr3 <= {AW{1'b0}};
            for(i3=0;i3<MAX_DELAY;i3=i3+1) mem3[i3] <= 16'sd0;
        end else if (in_data_vld_3) begin
            mem3[wr3] <= in_data_3;
            wr3 <= (wr3==MAX_DELAY-1) ? {AW{1'b0}} : wr3 + 1'b1;
        end
    end
    wire [AW-1:0] dly3 = (in_data_delay_3 >= MAX_DELAY) ? (MAX_DELAY-1) : in_data_delay_3[AW-1:0];
    wire [AW-1:0] rd3  = sub_mod(wr3, dly3);
    wire signed [15:0] d3 = mem3[rd3];
    wire signed [31:0] m3 = $signed(d3) * $signed(W2D_3);
    wire signed [15:0] w3 = m3[30:15];

    // ========== 通道 4 ==========
    reg signed [15:0] mem4 [0:MAX_DELAY-1];
    reg [AW-1:0] wr4; integer i4;
    always @(posedge clk or negedge rst_n) begin
        if(!rst_n) begin
            wr4 <= {AW{1'b0}};
            for(i4=0;i4<MAX_DELAY;i4=i4+1) mem4[i4] <= 16'sd0;
        end else if (in_data_vld_4) begin
            mem4[wr4] <= in_data_4;
            wr4 <= (wr4==MAX_DELAY-1) ? {AW{1'b0}} : wr4 + 1'b1;
        end
    end
    wire [AW-1:0] dly4 = (in_data_delay_4 >= MAX_DELAY) ? (MAX_DELAY-1) : in_data_delay_4[AW-1:0];
    wire [AW-1:0] rd4  = sub_mod(wr4, dly4);
    wire signed [15:0] d4 = mem4[rd4];
    wire signed [31:0] m4 = $signed(d4) * $signed(W2D_4);
    wire signed [15:0] w4 = m4[30:15];

    // ========== 通道 5 ==========
    reg signed [15:0] mem5 [0:MAX_DELAY-1];
    reg [AW-1:0] wr5; integer i5;
    always @(posedge clk or negedge rst_n) begin
        if(!rst_n) begin
            wr5 <= {AW{1'b0}};
            for(i5=0;i5<MAX_DELAY;i5=i5+1) mem5[i5] <= 16'sd0;
        end else if (in_data_vld_5) begin
            mem5[wr5] <= in_data_5;
            wr5 <= (wr5==MAX_DELAY-1) ? {AW{1'b0}} : wr5 + 1'b1;
        end
    end
    wire [AW-1:0] dly5 = (in_data_delay_5 >= MAX_DELAY) ? (MAX_DELAY-1) : in_data_delay_5[AW-1:0];
    wire [AW-1:0] rd5  = sub_mod(wr5, dly5);
    wire signed [15:0] d5 = mem5[rd5];
    wire signed [31:0] m5 = $signed(d5) * $signed(W2D_5);
    wire signed [15:0] w5 = m5[30:15];

    // ========== 通道 6 ==========
    reg signed [15:0] mem6 [0:MAX_DELAY-1];
    reg [AW-1:0] wr6; integer i6;
    always @(posedge clk or negedge rst_n) begin
        if(!rst_n) begin
            wr6 <= {AW{1'b0}};
            for(i6=0;i6<MAX_DELAY;i6=i6+1) mem6[i6] <= 16'sd0;
        end else if (in_data_vld_6) begin
            mem6[wr6] <= in_data_6;
            wr6 <= (wr6==MAX_DELAY-1) ? {AW{1'b0}} : wr6 + 1'b1;
        end
    end
    wire [AW-1:0] dly6 = (in_data_delay_6 >= MAX_DELAY) ? (MAX_DELAY-1) : in_data_delay_6[AW-1:0];
    wire [AW-1:0] rd6  = sub_mod(wr6, dly6);
    wire signed [15:0] d6 = mem6[rd6];
    wire signed [31:0] m6 = $signed(d6) * $signed(W2D_6);
    wire signed [15:0] w6 = m6[30:15];

    // ========== 通道 7 ==========
    reg signed [15:0] mem7 [0:MAX_DELAY-1];
    reg [AW-1:0] wr7; integer i7;
    always @(posedge clk or negedge rst_n) begin
        if(!rst_n) begin
            wr7 <= {AW{1'b0}};
            for(i7=0;i7<MAX_DELAY;i7=i7+1) mem7[i7] <= 16'sd0;
        end else if (in_data_vld_7) begin
            mem7[wr7] <= in_data_7;
            wr7 <= (wr7==MAX_DELAY-1) ? {AW{1'b0}} : wr7 + 1'b1;
        end
    end
    wire [AW-1:0] dly7 = (in_data_delay_7 >= MAX_DELAY) ? (MAX_DELAY-1) : in_data_delay_7[AW-1:0];
    wire [AW-1:0] rd7  = sub_mod(wr7, dly7);
    wire signed [15:0] d7 = mem7[rd7];
    wire signed [31:0] m7 = $signed(d7) * $signed(W2D_7);
    wire signed [15:0] w7 = m7[30:15];

    // ========== 通道 8 ==========
    reg signed [15:0] mem8 [0:MAX_DELAY-1];
    reg [AW-1:0] wr8; integer i8;
    always @(posedge clk or negedge rst_n) begin
        if(!rst_n) begin
            wr8 <= {AW{1'b0}};
            for(i8=0;i8<MAX_DELAY;i8=i8+1) mem8[i8] <= 16'sd0;
        end else if (in_data_vld_8) begin
            mem8[wr8] <= in_data_8;
            wr8 <= (wr8==MAX_DELAY-1) ? {AW{1'b0}} : wr8 + 1'b1;
        end
    end
    wire [AW-1:0] dly8 = (in_data_delay_8 >= MAX_DELAY) ? (MAX_DELAY-1) : in_data_delay_8[AW-1:0];
    wire [AW-1:0] rd8  = sub_mod(wr8, dly8);
    wire signed [15:0] d8 = mem8[rd8];
    wire signed [31:0] m8 = $signed(d8) * $signed(W2D_8);
    wire signed [15:0] w8 = m8[30:15];

    // ========== 通道 9 ==========
    reg signed [15:0] mem9 [0:MAX_DELAY-1];
    reg [AW-1:0] wr9; integer i9;
    always @(posedge clk or negedge rst_n) begin
        if(!rst_n) begin
            wr9 <= {AW{1'b0}};
            for(i9=0;i9<MAX_DELAY;i9=i9+1) mem9[i9] <= 16'sd0;
        end else if (in_data_vld_9) begin
            mem9[wr9] <= in_data_9;
            wr9 <= (wr9==MAX_DELAY-1) ? {AW{1'b0}} : wr9 + 1'b1;
        end
    end
    wire [AW-1:0] dly9 = (in_data_delay_9 >= MAX_DELAY) ? (MAX_DELAY-1) : in_data_delay_9[AW-1:0];
    wire [AW-1:0] rd9  = sub_mod(wr9, dly9);
    wire signed [15:0] d9 = mem9[rd9];
    wire signed [31:0] m9 = $signed(d9) * $signed(W2D_9);
    wire signed [15:0] w9 = m9[30:15];

    // ========== 通道 10 ==========
    reg signed [15:0] mem10 [0:MAX_DELAY-1];
    reg [AW-1:0] wr10; integer i10;
    always @(posedge clk or negedge rst_n) begin
        if(!rst_n) begin
            wr10 <= {AW{1'b0}};
            for(i10=0;i10<MAX_DELAY;i10=i10+1) mem10[i10] <= 16'sd0;
        end else if (in_data_vld_10) begin
            mem10[wr10] <= in_data_10;
            wr10 <= (wr10==MAX_DELAY-1) ? {AW{1'b0}} : wr10 + 1'b1;
        end
    end
    wire [AW-1:0] dly10 = (in_data_delay_10 >= MAX_DELAY) ? (MAX_DELAY-1) : in_data_delay_10[AW-1:0];
    wire [AW-1:0] rd10  = sub_mod(wr10, dly10);
    wire signed [15:0] d10 = mem10[rd10];
    wire signed [31:0] m10 = $signed(d10) * $signed(W2D_10);
    wire signed [15:0] w10 = m10[30:15];

    // ========== 通道 11 ==========
    reg signed [15:0] mem11 [0:MAX_DELAY-1];
    reg [AW-1:0] wr11; integer i11;
    always @(posedge clk or negedge rst_n) begin
        if(!rst_n) begin
            wr11 <= {AW{1'b0}};
            for(i11=0;i11<MAX_DELAY;i11=i11+1) mem11[i11] <= 16'sd0;
        end else if (in_data_vld_11) begin
            mem11[wr11] <= in_data_11;
            wr11 <= (wr11==MAX_DELAY-1) ? {AW{1'b0}} : wr11 + 1'b1;
        end
    end
    wire [AW-1:0] dly11 = (in_data_delay_11 >= MAX_DELAY) ? (MAX_DELAY-1) : in_data_delay_11[AW-1:0];
    wire [AW-1:0] rd11  = sub_mod(wr11, dly11);
    wire signed [15:0] d11 = mem11[rd11];
    wire signed [31:0] m11 = $signed(d11) * $signed(W2D_11);
    wire signed [15:0] w11 = m11[30:15];

    // ========== 通道 12 ==========
    reg signed [15:0] mem12 [0:MAX_DELAY-1];
    reg [AW-1:0] wr12; integer i12;
    always @(posedge clk or negedge rst_n) begin
        if(!rst_n) begin
            wr12 <= {AW{1'b0}};
            for(i12=0;i12<MAX_DELAY;i12=i12+1) mem12[i12] <= 16'sd0;
        end else if (in_data_vld_12) begin
            mem12[wr12] <= in_data_12;
            wr12 <= (wr12==MAX_DELAY-1) ? {AW{1'b0}} : wr12 + 1'b1;
        end
    end
    wire [AW-1:0] dly12 = (in_data_delay_12 >= MAX_DELAY) ? (MAX_DELAY-1) : in_data_delay_12[AW-1:0];
    wire [AW-1:0] rd12  = sub_mod(wr12, dly12);
    wire signed [15:0] d12 = mem12[rd12];
    wire signed [31:0] m12 = $signed(d12) * $signed(W2D_12);
    wire signed [15:0] w12 = m12[30:15];

    // ========== 通道 13 ==========
    reg signed [15:0] mem13 [0:MAX_DELAY-1];
    reg [AW-1:0] wr13; integer i13;
    always @(posedge clk or negedge rst_n) begin
        if(!rst_n) begin
            wr13 <= {AW{1'b0}};
            for(i13=0;i13<MAX_DELAY;i13=i13+1) mem13[i13] <= 16'sd0;
        end else if (in_data_vld_13) begin
            mem13[wr13] <= in_data_13;
            wr13 <= (wr13==MAX_DELAY-1) ? {AW{1'b0}} : wr13 + 1'b1;
        end
    end
    wire [AW-1:0] dly13 = (in_data_delay_13 >= MAX_DELAY) ? (MAX_DELAY-1) : in_data_delay_13[AW-1:0];
    wire [AW-1:0] rd13  = sub_mod(wr13, dly13);
    wire signed [15:0] d13 = mem13[rd13];
    wire signed [31:0] m13 = $signed(d13) * $signed(W2D_13);
    wire signed [15:0] w13 = m13[30:15];

    // ========== 通道 14 ==========
    reg signed [15:0] mem14 [0:MAX_DELAY-1];
    reg [AW-1:0] wr14; integer i14;
    always @(posedge clk or negedge rst_n) begin
        if(!rst_n) begin
            wr14 <= {AW{1'b0}};
            for(i14=0;i14<MAX_DELAY;i14=i14+1) mem14[i14] <= 16'sd0;
        end else if (in_data_vld_14) begin
            mem14[wr14] <= in_data_14;
            wr14 <= (wr14==MAX_DELAY-1) ? {AW{1'b0}} : wr14 + 1'b1;
        end
    end
    wire [AW-1:0] dly14 = (in_data_delay_14 >= MAX_DELAY) ? (MAX_DELAY-1) : in_data_delay_14[AW-1:0];
    wire [AW-1:0] rd14  = sub_mod(wr14, dly14);
    wire signed [15:0] d14 = mem14[rd14];
    wire signed [31:0] m14 = $signed(d14) * $signed(W2D_14);
    wire signed [15:0] w14 = m14[30:15];

    // ========== 通道 15 ==========
    reg signed [15:0] mem15 [0:MAX_DELAY-1];
    reg [AW-1:0] wr15; integer i15;
    always @(posedge clk or negedge rst_n) begin
        if(!rst_n) begin
            wr15 <= {AW{1'b0}};
            for(i15=0;i15<MAX_DELAY;i15=i15+1) mem15[i15] <= 16'sd0;
        end else if (in_data_vld_15) begin
            mem15[wr15] <= in_data_15;
            wr15 <= (wr15==MAX_DELAY-1) ? {AW{1'b0}} : wr15 + 1'b1;
        end
    end
    wire [AW-1:0] dly15 = (in_data_delay_15 >= MAX_DELAY) ? (MAX_DELAY-1) : in_data_delay_15[AW-1:0];
    wire [AW-1:0] rd15  = sub_mod(wr15, dly15);
    wire signed [15:0] d15 = mem15[rd15];
    wire signed [31:0] m15 = $signed(d15) * $signed(W2D_15);
    wire signed [15:0] w15 = m15[30:15];

    // ---------------------------
    // 树形求和（16 -> 1），再做平均 (>>4) 与归一化
    // ---------------------------
    reg signed [16:0] s1_0, s1_1, s1_2, s1_3, s1_4, s1_5, s1_6, s1_7;
    reg signed [17:0] s2_0, s2_1, s2_2, s2_3;
    reg signed [18:0] s3_0, s3_1;
    reg signed [19:0] s4;

    reg vld_d1, vld_d2, vld_d3;

    wire signed [15:0] avg16 = s4[19:4]; // >>4 平均
    wire signed [47:0] prod_norm = $signed(avg16) * $signed(NORM_Q15); // 16*32=48b
    wire signed [32:0] s33 = prod_norm[47:15]; // Q1.15

    wire sat_pos = (s33 > 33'sd32767);
    wire sat_neg = (s33 < -33'sd32768);
    wire signed [15:0] out_q15 = sat_pos ? 16'sd32767 :
                                 sat_neg ? -16'sd32768 :
                                 s33[15:0];

    always @(posedge clk or negedge rst_n) begin
        if(!rst_n) begin
            vld_d1<=1'b0; vld_d2<=1'b0; vld_d3<=1'b0;
            s1_0<=0; s1_1<=0; s1_2<=0; s1_3<=0; s1_4<=0; s1_5<=0; s1_6<=0; s1_7<=0;
            s2_0<=0; s2_1<=0; s2_2<=0; s2_3<=0;
            s3_0<=0; s3_1<=0;
            s4<=0;
            out_proc_data<=16'sd0; out_proc_data_vld<=1'b0;
        end else begin
            // stage1
            s1_0 <= w0  + w1;
            s1_1 <= w2  + w3;
            s1_2 <= w4  + w5;
            s1_3 <= w6  + w7;
            s1_4 <= w8  + w9;
            s1_5 <= w10 + w11;
            s1_6 <= w12 + w13;
            s1_7 <= w14 + w15;
            vld_d1 <= in_data_vld_0; // 16 路同步

            // stage2
            s2_0 <= s1_0 + s1_1;
            s2_1 <= s1_2 + s1_3;
            s2_2 <= s1_4 + s1_5;
            s2_3 <= s1_6 + s1_7;
            vld_d2 <= vld_d1;

            // stage3
            s3_0 <= s2_0 + s2_1;
            s3_1 <= s2_2 + s2_3;
            vld_d3 <= vld_d2;

            // stage4
            s4 <= s3_0 + s3_1;

            // 输出（带归一化与饱和）
            out_proc_data     <= out_q15;
            out_proc_data_vld <= vld_d3;
        end
    end
endmodule


